package com.vocabulary.service;

import java.util.*;
import java.sql.*;
import java.util.logging.Logger;
import java.util.logging.Level;
import org.apache.commons.math3.analysis.UnivariateFunction;
import org.apache.commons.math3.analysis.solvers.BrentSolver;
import org.apache.commons.math3.analysis.solvers.UnivariateSolver;

public class VocabularyEstimator {
    private static final Logger LOGGER = Logger.getLogger(VocabularyEstimator.class.getName());
    private static final int MIN_TEST_WORDS = 20;
    private static final int MAX_TEST_WORDS = 50;
    private static final double CONFIDENCE_THRESHOLD = 0.95;
    private static final double MAX_VOCABULARY_SIZE = 100000; // 最大词汇量估计值
    
    private final Connection connection;
    private final Random random;
    
    public VocabularyEstimator(Connection connection) {
        this.connection = connection;
        this.random = new Random();
        try {
            if (connection != null && !connection.isClosed()) {
                System.out.println("[数据库连接] 成功");
            } else {
                System.out.println("[数据库连接] 失败");
            }
        } catch (Exception e) {
            System.out.println("[数据库连接] 检查异常: " + e.getMessage());
        }
    }
    
    public VocabularyEstimate estimateVocabulary(List<WordResponse> responses) {
        if (responses.size() < MIN_TEST_WORDS) {
            throw new IllegalArgumentException("需要至少 " + MIN_TEST_WORDS + " 个单词的测试结果");
        }
        // 修正版：分层加权法
        double weightedSize = calculateWeightedVocabularySize(responses);
        // 修正版：简化IRT法
        double theta = estimateTheta(responses);
        double irtSize = calculateIRTVocabularySize(theta);
        // 综合两种方法，IRT权重降低
        double estimatedSize = 0.8 * weightedSize + 0.2 * irtSize;
        ConfidenceInterval confidenceInterval = calculateConfidenceInterval(responses, estimatedSize);
        double correctRate = calculateCorrectRate(responses);
        return new VocabularyEstimate(
            Math.round(estimatedSize),
            confidenceInterval,
            correctRate
        );
    }
    
    // 修正版分层加权法
    private double calculateWeightedVocabularySize(List<WordResponse> responses) {
        // 用实际区间长度作为每层代表词量
        int[] totalPerLevel = {10000, 2800, 1200, 1000, 2500, 1000, 1050, 450}; // A~H层区间长度
        double[] weights = {1, 1, 0.8, 0.7, 0.6, 0.5, 0.5, 0.5}; // A~H层权重，降低低等级权重
        int[] correct = new int[8];
        int[] total = new int[8];
        for (WordResponse r : responses) {
            int idx = 8 - r.getWord().getDifficultyLevel();
            total[idx]++;
            if (r.isCorrect()) correct[idx]++;
        }
        double vocab = 0;
        for (int i = 0; i < 8; i++) {
            if (total[i] < 3) continue; // 答题数少于3题的层不计入
            // 贝叶斯平滑
            double rate = (correct[i] + 1.0) / (total[i] + 2.0);
            vocab += rate * totalPerLevel[i] * weights[i];
        }
        return vocab;
    }
    
    // 简化IRT法：sigmoid平滑
    private double estimateTheta(List<WordResponse> responses) {
        double avgDifficulty = calculateAverageDifficulty(responses);
        double correctRate = calculateCorrectRate(responses);
        // 防止除零
        if (correctRate <= 0.01) correctRate = 0.01;
        if (correctRate >= 0.99) correctRate = 0.99;
        return avgDifficulty + Math.log(correctRate/(1-correctRate));
    }
    
    private double calculateIRTVocabularySize(double theta) {
        int[] totalPerLevel = {5000, 4000, 3000, 2000, 1000, 500, 300, 200};
        double vocab = 0;
        for (int i = 0; i < 8; i++) {
            // sigmoid平滑
            double prob = 1.0 / (1.0 + Math.exp(-(theta - (i+1))));
            vocab += prob * totalPerLevel[i];
        }
        return vocab;
    }
    
    private double calculateCorrectRate(List<WordResponse> responses) {
        return responses.stream()
                .filter(WordResponse::isCorrect)
                .count() / (double) responses.size();
    }
    
    private double calculateAverageDifficulty(List<WordResponse> responses) {
        return responses.stream()
                .mapToDouble(r -> r.getWord().getDifficultyLevel())
                .average()
                .orElse(0.0);
    }
    
    private ConfidenceInterval calculateConfidenceInterval(List<WordResponse> responses, double estimatedSize) {
        // 使用Fisher信息矩阵计算标准误差
        double standardError = calculateStandardError(responses, estimatedSize);
        double margin = 1.96 * standardError; // 95% 置信区间
        
        return new ConfidenceInterval(
            Math.round(estimatedSize * (1 - margin)),
            Math.round(estimatedSize * (1 + margin))
        );
    }
    
    private double calculateStandardError(List<WordResponse> responses, double estimatedSize) {
        // 计算Fisher信息矩阵的逆矩阵的对角线元素
        double information = 0.0;
        
        for (WordResponse response : responses) {
            double wordFrequency = getWordFrequency(response.getWord());
            double probability = calculateWordProbability(wordFrequency, estimatedSize);
            double derivative = calculateProbabilityDerivative(wordFrequency, estimatedSize);
            
            information += Math.pow(derivative, 2) / (probability * (1 - probability));
        }
        
        return Math.sqrt(1.0 / information);
    }
    
    private double calculateProbabilityDerivative(double wordFrequency, double vocabularySize) {
        // 计算概率对词汇量的导数
        double logRatio = Math.log(wordFrequency) - Math.log(vocabularySize);
        double expTerm = Math.exp(-logRatio);
        return expTerm / (vocabularySize * Math.pow(1 + expTerm, 2));
    }
    
    private double calculateWordProbability(double wordFrequency, double vocabularySize) {
        double logRatio = Math.log(wordFrequency) - Math.log(vocabularySize);
        return 1.0 / (1.0 + Math.exp(-logRatio));
    }
    
    private double getWordFrequency(Word word) {
        // 优化：根据难度级别分配更有区分度的词频值
        switch (word.getDifficultyLevel()) {
            case 8: return 100000; // A
            case 7: return 50000;  // B
            case 6: return 20000;  // C
            case 5: return 10000;  // D
            case 4: return 5000;   // E
            case 3: return 2000;   // F
            case 2: return 1000;   // G
            case 1: return 500;    // H
            default: return 1000;
        }
    }
    
    // 难度映射
    private static final String[] TABLES = {"A","B","C","D","E","F","G","H"};
   //普通分层抽取未被调用
    public List<Word> generateTest(int wordCount) {
        List<Word> testWords = new ArrayList<>();
        int perTable = wordCount / TABLES.length;
        int remainder = wordCount % TABLES.length;
        for (int i = 0; i < TABLES.length; i++) {
            String table = TABLES[i];
            int difficulty = TABLES.length - i; // A=8, H=1
            int need = perTable + (i < remainder ? 1 : 0); // 前remainder个表多取一个
            String sql = "SELECT Word FROM " + table + " ORDER BY DBMS_RANDOM.VALUE";
            try (
                PreparedStatement stmt = connection.prepareStatement(sql);
                ResultSet rs = stmt.executeQuery()
            ) {
                int count = 0;
                while (rs.next() && count < need) {
                    testWords.add(new Word(rs.getString("Word"), difficulty));
                    count++;
                }
            } catch (SQLException e) {
                LOGGER.log(Level.SEVERE, "生成测试时发生错误", e);
                throw new RuntimeException("无法生成测试", e);
            }
        }
        Collections.shuffle(testWords);
        return testWords;
    }
    
    // 分层自适应+IRT简化版：动态生成测试题目
    public List<Word> generateAdaptiveTest(int wordCount) {
        List<Word> testWords = new ArrayList<>();
        Set<String> usedWords = new HashSet<>();
        int currentAbilityLevel = 4; // 初始中等难度（E表）
        Random rand = new Random();
        for (int i = 0; i < wordCount; i++) {
            Word nextWord = getNextWord(currentAbilityLevel, usedWords);
            if (nextWord == null) {
                // 如果该层单词用完，随机从其他层补充
                for (int level = 8; level >= 1; level--) {
                    nextWord = getNextWord(level, usedWords);
                    if (nextWord != null) break;
                }
            }
            if (nextWord == null) break; // 所有单词都用完
            testWords.add(nextWord);
            usedWords.add(nextWord.getWord());
            // 简化IRT：模拟用户答题（实际应由外部传入答题结果）
            // 这里只做演示，实际答题后应由外部调整currentAbilityLevel
            // 例如：答对 currentAbilityLevel++，答错 currentAbilityLevel--
            // 这里默认交替提升/降低
            if (i % 2 == 0) {
                currentAbilityLevel = Math.min(8, currentAbilityLevel + 1);
            } else {
                currentAbilityLevel = Math.max(1, currentAbilityLevel - 1);
            }
        }
        return testWords;
    }

    // 从指定难度层随机抽取未用过的单词
    private Word getNextWord(int abilityLevel, Set<String> usedWords) {
        String table = TABLES[8 - abilityLevel]; // A=8, H=1
        String sql = "SELECT Word FROM " + table + " ORDER BY DBMS_RANDOM.VALUE";
        try (
            PreparedStatement stmt = connection.prepareStatement(sql);
            ResultSet rs = stmt.executeQuery()
        ) {
            while (rs.next()) {
                String wordStr = rs.getString("Word");
                if (!usedWords.contains(wordStr)) {
                    return new Word(wordStr, abilityLevel);
                }
            }
        } catch (SQLException e) {
            LOGGER.log(Level.SEVERE, "自适应抽题时发生错误", e);
        }
        return null;
    }
    
    // 内部类定义
    public static class Word {
        private final String word;
        private final int difficultyLevel; // 用表名映射

        public Word(String word, int difficultyLevel) {
            this.word = word;
            this.difficultyLevel = difficultyLevel;
        }

        public String getWord() { return word; }
        public int getDifficultyLevel() { return difficultyLevel; }
    }
    
    public static class WordResponse {
        private final Word word;
        private final boolean correct;
        
        public WordResponse(Word word, boolean correct) {
            this.word = word;
            this.correct = correct;
        }
        
        public boolean isCorrect() { return correct; }
        public Word getWord() { return word; }
    }
    
    public static class VocabularyEstimate {
        private final long estimatedSize;
        private final ConfidenceInterval confidenceInterval;
        private final double correctRate;
        
        public VocabularyEstimate(long estimatedSize, ConfidenceInterval confidenceInterval, double correctRate) {
            this.estimatedSize = estimatedSize;
            this.confidenceInterval = confidenceInterval;
            this.correctRate = correctRate;
        }
        
        public long getEstimatedSize() { return estimatedSize; }
        public ConfidenceInterval getConfidenceInterval() { return confidenceInterval; }
        public double getCorrectRate() { return correctRate; }
    }
    
    public static class ConfidenceInterval {
        private final long lowerBound;
        private final long upperBound;
        
        public ConfidenceInterval(long lowerBound, long upperBound) {
            this.lowerBound = lowerBound;
            this.upperBound = upperBound;
        }
        
        public long getLowerBound() { return lowerBound; }
        public long getUpperBound() { return upperBound; }
    }

    // 支持GUI自适应流程的重载方法
    public Word generateAdaptiveTest(int wordCount, int abilityLevel, Set<String> usedWords) {
        // 只抽取一个单词，指定难度和已用单词
        Word nextWord = getNextWord(abilityLevel, usedWords);
        if (nextWord == null) {
            // 如果该层单词用完，随机从其他层补充
            for (int level = 8; level >= 1; level--) {
                nextWord = getNextWord(level, usedWords);
                if (nextWord != null) break;
            }
        }
        return nextWord;
    }
} 